<template>
  <div ref="threeContainer" class="three-container"></div>
</template>

<script>
import * as THREE from "three";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

let scene = null; // 场景需要定义到全局
let aaa = "lalalalalal";
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

export default {
  name: "ThreeModel",
  data() {
    return {
      camera: null,
      renderer: null,
      controls: null,
    };
  },
  mounted() {
    console.log("////////////");

    this.initThree();
    this.loadModel();
    this.initControls();
    this.addBackground();
    this.animate();
  },
  unmounted() {
    this.renderer.domElement.removeEventListener("click", this.onClick);
  },
  methods: {
    /**
     * 创建场景
     */
    initThree() {
      this.scene = new THREE.Scene();
      this.scene.rotation.y = 20.75;
      this.scene.rotation.x = 10;
      this.scene.rotation.z = 0;

      // 创建相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        this.$refs.threeContainer.clientWidth /
          this.$refs.threeContainer.clientHeight,
        1,
        1000
      );
      this.camera.position.z = 13.9;
      this.camera.position.y = -100;
      this.camera.position.x = 45;

      // 把画面放大一点
      // this.camera.zoom = 1
      // this.camera.updateProjectionMatrix()

      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer();
      this.renderer.setSize(
        this.$refs.threeContainer.clientWidth,
        this.$refs.threeContainer.clientHeight
      );
      this.$refs.threeContainer.appendChild(this.renderer.domElement);

      // 添加光源
      const light = new THREE.DirectionalLight(0xa1a1a1, 1);
      light.position.set(10, 5, 5).normalize();
      this.scene.add(light);

      // 注册点击事件
      this.renderer.domElement.addEventListener("click", this.onClick, false);
    },
    /**
     * 点击事件
     * @param {*} event
     */
    onClick(event) {
      // 将鼠标位置归一化到-1到1的范围（相对于渲染器的尺寸）
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

      // 使用相机和鼠标向量来投射射线
      raycaster.setFromCamera(mouse, this.camera);

      // 检查与哪些对象相交，并处理相交的对象
      const intersects = raycaster.intersectObjects(this.scene.children);
      if (intersects.length > 0) {
        intersects.forEach((o) => {
          const intersectedObject = o.object;
          // 在这里处理被点击的对象，例如改变颜色、显示信息等
          console.log("点击-on object:", intersectedObject);
          if (intersectedObject.parent.name == "tank") {
            // 改变颜色
            intersectedObject.material.color.set(0xffffff);
          }
        });
      }
    },
    /**
     * 鼠标互动
     */
    initControls() {
      // 假设你已经有了相机、渲染器和场景
      const controls = new OrbitControls(this.camera, this.renderer.domElement);

      // 设置控制器的属性，例如最小和最大距离、旋转速度等
      controls.minDistance = 1;
      controls.maxDistance = 500;
      controls.enableDamping = true; // 启用阻尼效果，使互动更加流畅
      controls.dampingFactor = 0.25; // 阻尼系数
      controls.screenSpacePanning = true; // 是否允许平面移动
      this.controls = controls;
    },
    /**
     * 场景增加背景
     */
    addBackground() {
      // 添加纯色为背景
      this.renderer.setClearColor(0xcccccc); // 设置背景颜色为天空色

      // 创建一个新的纹理加载器
      const textureLoader = new THREE.TextureLoader();
      const scene = this.scene;
      // 加载图像纹理
      textureLoader.load(
        //   "http://cdn.yhxweb.cn/3d-sucai/BA_64_D.jpg", // 图像路径
        function (texture) {
          // 设置name
          texture.name = "background";
          // 创建一个平面几何体（或其他几何体）
          const geometry = new THREE.PlaneGeometry(500, 500); // 假设你的场景宽度和高度是500
          const material = new THREE.MeshBasicMaterial({ map: texture });
          // 创建一个网格并添加到场景中
          const plane = new THREE.Mesh(geometry, material);
          plane.position.z = 0; // 根据你的场景深度调整位置
          scene.add(plane);
        },
        // 可选的加载进度回调函数
        undefined,
        // 可选的加载错误回调函数
        function (err) {
          console.error("An error happened while loading the texture.");
        }
      );
    },
    /**
     * 初始化模型
     */
    loadModel() {
      const loader = new OBJLoader();
      // 加载.obj模型文件
      loader.load(
        // "http://cdn.yhxweb.cn/3d-sucai/OBJ_7020.obj", // 替换为你的.obj文件的URL（园林）
        //文件放在public下，使用'/'只想根文件夹
        "/public/models/dataStracture.obj", // 替换为你的.obj文件的URL（园林）
        (obj) => {
          this.scene.add(obj);
          // 设置name
          obj.name = "tank";
          // 设置模型的位置和缩放
          obj.position.set(0, 0, 0);
          obj.scale.set(-1, -1, -1);
          // 设置模型的旋转角度
          obj.rotation.x = 1.6;
          obj.rotation.y = 2;
          console.log(obj, "objobj");
          // 设置模型颜色
          obj.traverse((child) => {
            console.log("child:", child);
            if (child instanceof THREE.Mesh) {
              console.log(child, "child.material.color");
              // console.log(child.material, "child.material.color");
              // child.material.forEach((item) => {
              //   item.color.set(0xffd4db);
              // });
              // child.material.color.set(0xffd4db); // 设置颜色
              // child.material[0].color.set(0xffd4db); // 设置颜色
              // child.material[1].color.set(0xffd4db); // 设置颜色
              // child.material[2].color.set(0xffd4db); // 设置颜色
            }
          });
          // 将加载的模型添加到场景中
        },
        (xhr) => {
          console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
        },
        (error) => {
          console.error("An error happened", error);
        }
      );
    },
    /**
     * 动画
     */
    animate() {
      // 可以在这里添加动画逻辑，例如模型旋转
      // this.scene.rotation.y += 0.002
      // this.scene.rotation.x += 0.001

      // 更新控制器
      this.controls.update();

      this.renderer.render(this.scene, this.camera);
      // console.log(this.scene.rotation.x, this.scene.rotation.y)

      requestAnimationFrame(this.animate);
    },
  },
};
</script>

<style>
.three-container {
  width: 100%;
  height: calc(100vh - 175px);
  overflow: hidden;
}
</style>
